package com.tinfeng.uplevel;

import java.util.*;

public class JavaCollectionMap {
    // Java 集合
    // 在计算机科学中，集合是一组可变数量的数据项（也可能为 0 个）的组合，
    // 这些数据可能共享某些特征，需要以某种操作方式一起进行操作

    /**
     * Collection
     * java.util.Collection 接口的实现可用于存储 Java 对象。例如，慕课网的所有学生可以视为一个 Collection。
     *
     * Collection 又可以分为三个子接口，分别是：
     *
     * List：序列，必须按照顺序保存元素，因此它是有序的，允许重复；
     * Queue：队列，按照排队规则来确定对象产生的顺序，有序，允许重复；
     * Set：集，不能重复。
     *
     * Map
     * java.util.Map 接口的实现可用于表示 “键”（key）和 “值”（value）对象之间的映射。
     * 一个映射表示一组 “键” 对象，其中每一个 “键” 对象都映射到一个 “值” 对象。
     * 因此可以通过键来查找值。
     * 例如，慕课网的每一个学生都有他自己的账户积分，这个关联关系可以用 Map 来表示。
     */

    // 数组与集合的区别
    /**
     * 数组与集合
     * 在介绍集合的应用场景之前，我们先来看看数组和集合的对比。
     *
     * 我们知道数组和集合都用于存放一组数据，但数组的容量是固定大小的，而集合的容量是动态可变的；
     * 对于可存放的数据类型，数组既可以存放基本数据类型又可以存放引用数据类型，
     * 而集合只能存放引用数据类型，基本数据类型需要转换为对应的包装类才能存放到集合当中。
     */

    // 集合应用场景
    /**
     * 无法预测存储数据的数量：由于数组容量是固定大小，因此使用集合存储动态数量的数据更为合适；
     * 同时存储具有一对一关系的数据：例如存储慕课网学生的积分，为了方便检索对应学生的积分，可使用 Map 将慕课网学生的 uid 和对应的积分进行一对一关联；
     * 数据去重：使用数组实现需要遍历，效率低，而 Set 集合本身就具有不能重复的特性；
     * 需要数据的增删：使用数组实现增删操作需要遍历、移动数组中元素，如果操作频繁会导致效率降低。
     */

    // ArrayList 实现类
    /**
     *
     * ArrayList 可以理解为动态数组，它的容量可以动态增长。当添加元素时，如果发现容量已满，会自动扩容为原始大小的 1.5 倍。
     *
     * 3.2.1 构造方法
     * ArrayList()：构造一个初始容量为 10 的空列表；
     * ArrayList(int initialCapacity)：构造一个指定容量的空列表；
     * ArrayList(Collection<? extends E> c)：构造一个包含指定集合元素的列表，其顺序由集合的迭代器返回。
     */

    // 成员方法
    /**
     * 常用成员方法
     *
     * void add(E e)：将指定的元素追加到此列表的末尾；
     * void add(int index, E element)：将指定的元素插入此列表中的指定位置；
     * E remove(int index)：删除此列表中指定位置的元素；
     * boolean remove(Object o)：如果存在指定元素，则从该列表中删除第一次出现的该元素；
     * void clear()：从此列表中删除所有元素；
     * E set(int index, E element)：用指定的元素替换此列表中指定位置的元素；
     * E get(int index)：返回此列表中指定位置的元素；
     * boolean contains(Object o)：如果此列表包含指定的元素，则返回 true，否则返回 false；
     * int size()：返回该列表中元素的数量；
     * Object[] toArray()：以正确的顺序（从第一个元素到最后一个元素）返回一个包含此列表中所有元素的数组。
     */
    public static void main(String[] args) {
        // List arr = new ArrayList(); 这是原来
        List<Integer> arr = new ArrayList<>(); // 这样变成了泛型
        for (int i = 0; i <= 10 ; i++) {
            arr.add(i);
            System.out.println(arr);
        }
        ArrayList<String> str = new ArrayList<>();
        str.add("nm");         // 可直接输入字符，随机插入
        str.add("mmp");
        str.add(1,"cnm");  // 或者指定索引位置
        System.out.println(str);

//        str.remove(2); // 指定索引删除
//        System.out.println(str);
//        str.remove("nm"); // 指定字符删除，匹配第一个
//        System.out.println(str);
//
//        str.set(0,"mmm");   // 修改指定索引的值
//        System.out.println(str);
        for (int i = 0; i <str.size() ; i++) {  // 集合长度用size
            System.out.println(str.get(i));   // 取值
        }

        /**
         * LinkedList 实现类
         * LinkedList 是一个以双向链表实现的 List。和 ArrayList 一样，也按照索引位置排序，但它的元素是双向连接的，因此顺序访问的效率非常高，而随机访问的效率比较低。
         *
         * 构造方法:
         *
         * LinkedList()：构造一个空列表；
         * LinkedList(Collection<? extends E> c)：构造一个包含指定集合元素的列表，其顺序由集合的迭代器返回。
         *
         * 常用成员方法:
         *
         * void add(E e)：将指定的元素追加到此列表的末尾；
         * void add(int index, E element)：将指定的元素插入此列表中的指定位置；
         * void addFirst(E e)：将指定的元素插入此列表的开头；
         * vod addLast(E e)：将指定的元素添加到此列表的结尾；
         * E remove(int index)：删除此列表中指定位置的元素；
         * boolean remove(Object o)：如果存在指定元素，则从该列表中删除第一次出现的该元素；
         * void clear()：从此列表中删除所有元素；
         * E set(int index, E element)：用指定的元素替换此列表中指定位置的元素；
         * E get(int index)：返回此列表中指定位置的元素；
         * E getFirst()：返回此列表的第一个元素；
         * E getLast()：返回此列表的最后一个元素；
         * boolean contains(Object o)：如果此列表包含指定的元素，则返回 true，否则返回 false；
         * int size()：返回该列表中元素的数量；
         * Object[] toArray()：以正确的顺序（从第一个元素到最后一个元素）返回一个包含此列表中所有元素的数组。
         */

        // set集合
        HashSet<String> hashSet = new HashSet<>();
        hashSet.add("java");
        hashSet.add("python");
        hashSet.add("php");
        System.out.println(hashSet);

        // 获取 hashSet 中元素的迭代器
        Iterator<String> iterator = hashSet.iterator();
        while (iterator.hasNext()){
            System.out.println(iterator.next());
        }

        //Map集合
        /**
         *
         * Map 集合
         * 概念和特性:
         * 我们已经知道 Map 是以键值对（key-value）的形式存储的对象之间的映射，key-value 是以 java.util.Map.Entry 类型的对象实例存在。
         *
         * 可以使用键来查找值，一个映射中不能包含重复的键，但值是可以重复的。每个键最多只能映射到一个值。
         *
         * HashMap 实现类:
         * HashMap 是 java.util.Map 接口最常用的一个实现类，前面所学的 HashSet 底层就是通过 HashMap 来实现的，HashMap 允许使用 null 键和 null 值。
         *
         * 构造方法:
         * HashMap()：构造一个新的空映射；默认的初始容量为 16（最常用），负载系数为 0.75；
         *
         * HashMap(int initialCapacity)：构造一个新的空映射； 具有指定的初始容量，负载系数为 0.75；
         *
         * HashMap(int initialCapacity, float loadFactor)：构造一个新的空映射； 支持的 HashMap 实例具有指定的初始容量和指定的负载系数；
         *
         * HashSet(Map<? extends K, ? extends V> m)：构造一个新映射，其中包含指定映射相同。
         *
         * 常用成员方法:
         *
         * void clear()：从该映射中删除所有映射；
         * Set<Map, Entry<K, V>> entrySet：返回此映射中包含的映射的集合；
         * V get(Object key)：返回指定键映射到的值，如果该映射不包含键的映射，则返回 null；
         * Set<K> keySet：返回此映射中包含的键的结合；
         * V put(K key, V value)：将指定值与此映射中指定键关联；
         * V remove(Object key)：如果存在，则从此映射中删除指定键的映射。
         * Collection<V> values：返回此映射中包含的集合。
         */
        Map<String, String> map = new HashMap<>();
        // 存值
        map.put("English","英语");
        map.put("Chinese","汉语");
        map.put("Java","咖啡");
        System.out.println(map);
        // 删除
        map.remove("Chinese");
        System.out.println("删了汉语"+map);

        //修改
        map.put("Java","编程语言");
        System.out.println("修改后的"+map);

        //遍历map  通过遍历entrySet方法得到 key-value 映射：
        Set<Map.Entry<String, String>> entries = map.entrySet();
        for (Map.Entry<String, String> entry : entries) {
            System.out.println(entry.getKey()+"-"+entry.getValue());
        }

        // 查找集合中为English的值
        Set<String> keySet = map.keySet();
        for (String key : keySet) {
            if (key.equals("English")) {
                System.out.println("找到，值为"+map.get(key));
                break;
            }
        }

    }
}
